package josephu

import "fmt"

type Boy struct {
	No   int
	Next *Boy
}

// 编写一个函数，构成一个单向的环形链表
// num:表示小孩的个数
// *Boy:返回该环形的链表的第一个小孩的指针
func Add(num int) *Boy {
	first := &Boy{} //空结点
	curBoy := &Boy{}
	//判断
	if num < 1 {
		fmt.Println("num的值不对")
		return first
	}
	//分析构成循环列表，需要一个辅助指针
	//循环的构建这个环形链表
	for i := 1; i <= num; i++ {
		boy := &Boy{
			No: i,
		}
		if i == 1 { //第一个小孩，第一个比较特殊
			first = boy
			curBoy = boy
			curBoy.Next = first //

		} else {
			curBoy.Next = boy
			curBoy = boy
			curBoy.Next = first //构造环形链表
		}
	}
	return first
}

// 进行游戏函数
func PlayGame(first *Boy, startNo, countNUm int) {
	//处理空链表
	if first.Next == nil {
		fmt.Println("空链表，没有小孩")
	}
	//需要辅助指针
	tail := first
	//让tail执行环形链表的最后一个小孩，非常重要
	//因为tail在删除小孩是需要用到
	for {
		if tail.Next == first { // 说明tail到了最后
			break
		}
		tail = tail.Next
	}
	//让first移动到startNo，后面删除以first为准
	for i := 0; i < startNo-1; i++ {
		first = first.Next
		tail = tail.Next
	}
	//继续移动，开始删，数到countNum
	for {
		for i := 1; i <= countNUm-1; i++ {
			first = first.Next
			tail = tail.Next
		}
		//删除first这个
		fmt.Println(first.No, "这个小孩出圈")
		first = first.Next
		tail.Next = first
		//判断退出
		if tail == first {
			break
		}
	}
	fmt.Println("最后一个", first.No)
}

// 显示单向的环形链表
func ShowBoy(first *Boy) {
	//处理一下为空的环形链表
	if first.Next == nil {
		fmt.Println("链表为空，没有小孩")
		return
	}
	//创建一个指针，帮助遍历
	curBoy := first
	for {
		fmt.Println("小孩编号", curBoy.No)
		//退出条件
		if curBoy.Next == first {
			break
		}
		//移动
		curBoy = curBoy.Next
	}
}

func Testmain() {
	first := Add(5)
	ShowBoy(first)
	PlayGame(first, 2, 3)
}
